#include "log_backtracer.h"

namespace afcore {
namespace log {

CLogBackTracer::CLogBackTracer(const CLogBackTracer& that) {
  std::lock_guard<std::mutex> lock(that.mutex_);
  enable_ = that.Enabled();
  messages_ = that.messages_;
}

CLogBackTracer::CLogBackTracer(CLogBackTracer&& that) noexcept {
  std::lock_guard<std::mutex> lock(that.mutex_);
  enable_ = that.Enabled();
  messages_ = std::move(that.messages_);
}

CLogBackTracer& CLogBackTracer::operator=(CLogBackTracer that) {
  std::lock_guard<std::mutex> lock(mutex_);
  enable_ = that.Enabled();
  messages_ = std::move(that.messages_);
  return *this;
}

void CLogBackTracer::Enable(size_t size) {
  std::lock_guard<std::mutex> lock(mutex_);
  enable_.store(true, std::memory_order_relaxed);
  messages_ = CCircularQueue<CLogMessageBuffer>(size);
}

void CLogBackTracer::Disable() {
  std::lock_guard<std::mutex> lock(mutex_);
  enable_.store(false, std::memory_order_relaxed);
}

bool CLogBackTracer::Enabled() const {
  return enable_.load(std::memory_order_relaxed);
}

void CLogBackTracer::Append(const SLogMessage& msg) {
  std::lock_guard<std::mutex> lock(mutex_);
  messages_.EnQueue(CLogMessageBuffer{msg});
}

void CLogBackTracer::ForeachPop(std::function<void(const SLogMessage&)> fun) {
  std::lock_guard<std::mutex> lock(mutex_);
  while(!messages_.Empty()) {
    auto& msg = messages_.Front();
    fun(msg);
    messages_.DeQueue();
  }
}

} // !namespace log
} // !namespace afcore